import threading

import asynclientconnection
import _iodispatcher

from coffeetalk.protocol import ioml, requests, iotypes
from coffeetalk.utilities import iologger

class IOClientException(Exception):
    
    def __init__(self,errorMessage):
        self.errorMessage = errorMessage

    def __str__(self):
        return self.errorMessage
        
class IOTPClient(object):
    
    def __init__(self,config=None,host='127.0.0.1',port=3030,username='',password='',group='',userclass='Users',log=iologger.IONullLogger()):
        
        self.host = host
        self.port = port
        self.username = username
        self.password = password
        self.group = group
        self.userclass = userclass
        
        if config is not None and isinstance(config,iotypes.Connection):
            self.host = config.host
            self.port = config.port
            self.username = config.username
            self.password = config.password
            self.group = config.group
            self.userclass = config.userclass

        self.log = log
        
        self.dispatcher = _iodispatcher._IODispatcher(self,log=self.log)
        self.asynclient = asynclientconnection.IOAsyncClientConnection(self.host,self.port,self.log)
        
        self.asynclient.handle_connect = self.handle_connect
        self.asynclient.handle_disconnect = self.disconnect
        self.asynclient.process_message = self._handle_login_response
        loginrequest = requests.Login(self.username,self.password,self.group,userclass=self.userclass)
        self.send_request(loginrequest)
        
    def connect(self):
        self.asynclient.connect_client()
    
    def disconnect(self):
        self.asynclient.disconnect = True
        self.handle_disconnect()
       
    def handle_connect(self):
        self.log.log_error(iologger.DEBUG,'0.0.0.0',self.username,str(self),iologger.current_function(),'','')
    
    def handle_disconnect(self):
        self.log.log_error(iologger.DEBUG,'0.0.0.0',self.username,str(self),iologger.current_function(),'','')
    
    def _handle_redirect(self,redirect):
        pass
    
    def _handle_login_response(self,message):
        
        iomessage = ioml.IOML(iomlstring=message)
        if iomessage.headelement.attribs.has_key('type') and iomessage.headelement.attribs['type'] == 'responses.Authorized':
            self.asynclient.process_message = self.dispatcher.dispatch_message
            self.on_login()
        else:
            self.log.log_error(iologger.CRITICAL,'0.0.0.0',self.username,str(self),iologger.current_function(),'Unauthorized','')
            self.on_bad_login()
            
    def on_login(self):
        pass
    
    def on_bad_login(self):
        pass
    
    def send_request(self,request):
        
        if not isinstance(request,requests.Request):
            raise IOClientException('invalid request')
        
        if isinstance(request,requests.Subscribe) and self.dispatcher.subscription_exists(request.path):
            getrequest = requests.Get(requestid=request.requestid,path=request.path,on_success=request.on_success,on_error=request.on_error,**request.kwargs)
            self.dispatcher.add_request(request)
            self.asynclient.send_message(str(getrequest))
        else:
            self.dispatcher.add_request(request)
            self.asynclient.send_message(str(request))

class ThreadedIOTPClient(threading.Thread,IOTPClient):
    
    def __init__(self,config=None,host='127.0.0.1',port=3030,username='',password='',group='',userclass='Users',log=iologger.IONullLogger()):
        IOTPClient.__init__(self, config=config, host=host, port=port, username=username, password=password, group=group, userclass=userclass, log=log)
        threading.Thread.__init__(self)
        
    def run(self):
        self.connect()
        